1.Introduction

Wi-Fi networks are now more and more popular among urban residents. Some public places or private places have provided Wi-Fi networks to the public free of charge. Public Wi-Fi brings convenience to people’s lives and transportation. On the other hand, people’s behavior data recorded by Wi-Fi is an important data source. It can provide data for better urban planning. Of course, there is also a certain commercial value. The construction of public Wi-Fi in the city is an important step in building a smart city. Reasonable site selection can improve the efficiency of resource utilization.

2.Theme Review

The subway is a good way to travel on weekdays, it won’t be affected by traffic jams compared to other modes of transportation.In the spare time, cycling is a great way to relax and exercise.This notebook analyzes the current Wi-Fi station and traffic data(Subway and Bicycle) in New York City, finds potential deficiencies, and proposes corresponding strategies.

3.Data and Methods

Data: 1) NYC Free Public Wi-Fi 2) NYC Subway Routes 3) NYC Subway Stations 4) NYC Bicycle Routes 5) NYC Bicycle Parking Shelters

a.Statistics Analysis and Data Visualization

getwd()
[1] "/Users/afen/Documents/GitHub/WIFI_hotspot_analysis_based_NYC"
names(wifi_data)
 [1] "BORO"       "the_geom"   "TYPE"       "OBJECTID"   "PROVIDER"   "NAME"       "LAT"       
 [8] "LOCATION"   "LON"        "X"          "Y"          "LOCATION_T" "REMARKS"    "CITY"      
[15] "SSID"       "SOURCEID"   "ACTIVATED"  "BOROCODE"   "BORONAME"   "NTACODE"    "NTANAME"   
[22] "COUNDIST"   "POSTCODE"   "BOROCD"     "CT2010"     "BOROCT2010" "BIN"        "BBL"       
[29] "DOITT_ID"  
summary(wifi_data)
                                          the_geom              TYPE                      PROVIDER   
 POINT (-73.76955899961533 40.6871909999958)  :  14   Free        :2762   LinkNYC - Citybridge:1867  
 POINT (-73.93935699958523 40.812680999589254):   8   Limited Free: 581   SPECTRUM            : 343  
 POINT (-73.99797999992514 40.710249999883835):   8   Partner Site:   2   Transit Wireless    : 276  
 POINT (-73.9141379998959 40.81154399995916)  :   7                       ALTICEUSA           : 237  
 POINT (-73.94490899985944 40.805012999655474):   7                       Harlem              : 128  
 POINT (-73.98834699960128 40.69363599965358) :   7                       Downtown Brooklyn   : 100  
 (Other)                                      :3294                       (Other)             : 394  
      LAT                                LOCATION         LON               X                 Y         
 Min.   :40.51   Park Perimeter              :  42   Min.   :-74.24   Min.   : 916371   Min.   :125007  
 1st Qu.:40.70   Along Boardwalk and Beach   :  15   1st Qu.:-73.99   1st Qu.: 988242   1st Qu.:192750  
 Median :40.75   300 Jay Street              :  11   Median :-73.96   Median : 994923   Median :211164  
 Mean   :40.74   333 Adams St.               :   8   Mean   :-73.95   Mean   : 998079   Mean   :209724  
 3rd Qu.:40.79   110 Livingston St.          :   7   3rd Qu.:-73.93   3rd Qu.:1004358   3rd Qu.:228306  
 Max.   :40.90   North area off Richmond Terr:   6   Max.   :-73.71   Max.   :1063266   Max.   :268544  
                 (Other)                     :3256                                                      
          BORONAME   
 Bronx        : 316  
 Brooklyn     : 700  
 Manhattan    :1698  
 Queens       : 531  
 Staten Island: 100  
                     
                     
# Data visualization
library(ggplot2)
wifi_pro + geom_bar(aes(fill=TYPE)) + scale_fill_brewer(direction = -1,palette = "Green") + theme(axis.text.x = element_text(colour="grey20",size = 5,angle=45,hjust=.5,vjust=.5,face="plain"))
Unknown palette Green

wifi_boro + geom_bar(aes(fill=TYPE)) + scale_fill_brewer(palette = "Green",direction = -1)
Unknown palette Green

Choropleth and Heat map powered by carto[https://carto.com/] Choropleth and Heat map

b.Spatial Queries and Spatial Analysis

# use cartodb to do analysis from spatial database
library(RCurl)
library(bitops)
library(RJSONIO)
library(devtools)
library(CartoDB)
cartodb("zhoumaneo")
Without an API key you are limited to read-only
cartodb.test()
http://zhoumaneo.carto.com/api/v2/sql?api_key=&
cartodb("zhoumaneo", api.key="fb070799acad21d626b5ade94caa3542b7decd88")

1) Do some spatial queries and plot the results

library(rgdal)
bicycle_routes <- cartodb.collection(sql="SELECT * FROM bicycle_routes",method="GeoJSON")
bicycle_routes.SP <- readOGR(bicycle_routes,layer = 'OGRGeoJSON',verbose =FALSE)
Free_wifi_hotspot <- cartodb.collection(sql = "SELECT * FROM nyc_wi_fi_hotspot_locations WHERE type = 'Free'",method = "GeoJSON")
Free_wifi_hotspot.SP <- readOGR(Free_wifi_hotspot,layer = 'OGRGeoJSON',verbose = FALSE)
bicycle_parking_shelters <- cartodb.collection(sql="SELECT * FROM bicycle_parking_shelters",method = "GeoJSON")
bicycle_parking_shelters.SP <- readOGR(bicycle_parking_shelters,layer = 'OGRGeoJSON',verbose = FALSE)

This plot is to show the location relationship between free wifi hotspot and bicycle routes

plot(bicycle_routes.SP)
plot(Free_wifi_hotspot.SP,col = "red",add = TRUE)
plot(bicycle_parking_shelters.SP,col = "green",add = TRUE, pch = 20)

Limited_free_wifi_hotspot <- cartodb.collection(sql = "SELECT * FROM nyc_wi_fi_hotspot_locations WHERE type = 'Limited Free'",method = "GeoJSON")
Limited_free_wifi_hotspot.SP <- readOGR(Limited_free_wifi_hotspot,layer = 'OGRGeoJSON',verbose = FALSE)

This plot is to show the location relationship between limited free wifi hotspot and bicycle routes

plot(bicycle_routes.SP)
plot(Limited_free_wifi_hotspot.SP,col = "red",add = TRUE)
plot(bicycle_parking_shelters.SP, col = "green",add = TRUE, pch = 20)

subway_routes <- cartodb.collection(sql = "SELECT * FROM subway",method = "GeoJSON")
subway_routes.SP <- readOGR(subway_routes,layer = 'OGRGeoJSON',verbose = FALSE)
subway_stations <- cartodb.collection(sql = "SELECT * FROM subway_stations",method = "GeoJSON")
subway_stations.SP <- readOGR(subway_stations,layer = 'OGRGeoJSON',verbose = FALSE)

This plot is to show the location relationship between wifi hotspot and subway routes

plot(subway_routes.SP)
plot(subway_stations.SP,add = TRUE)
plot(Free_wifi_hotspot.SP,col = "green",add = TRUE)
plot(Limited_free_wifi_hotspot.SP,col = "dark green",add = TRUE)

2) Spatial analysis

The wifi signal is spread out by the wifi station. The signal strength decreases with distance. Generally, the Wi-Fi signal has a radiation distance of less than 100m. This notebook uses 100m as range to do buffer as the zones of signal covered. And then do some spatial intersect analysis to see the signal coverage of various subway lines and bicycle routes. Finally, I also use buffer and intersection to see the utilizations of wifi hotspot.

#Return buffers
wifi_buffers <- cartodb.collection(sql="SELECT cartodb_id,  ST_Buffer(the_geom::geography,100) as the_geom FROM nyc_wi_fi_hotspot_locations",method="GeoJSON")
# Plot the results
wifi_buffers.SP <- readOGR(wifi_buffers,layer = 'OGRGeoJSON',verbose =FALSE)
#Plot first 100 tree buffers
plot(wifi_buffers.SP[1:100,])

  • Wifi hotspot locations buffer by carto wifi buffer

  • The signal coverage of various subway lines. subway_routes

  • The signal coverage of various bicycle routes. bicycle routes

3) Utilization of wifi hotspot

subway_routes_buffers <- cartodb.collection(sql="SELECT cartodb_id,  ST_Buffer(the_geom::geography,100) as the_geom FROM subway",method="GeoJSON")
# Plot the results
subway_routes_buffers.SP <- readOGR(subway_routes_buffers,layer = 'OGRGeoJSON',verbose =FALSE)
#Plot first 100 tree buffers
plot(subway_routes_buffers.SP)

Find the wifi hotspots that do not intersect with the buffer of subway routes

wifi_hotspot_without_subway_routes <- cartodb.collection(sql = "SELECT a.* FROM nyc_wi_fi_hotspot_locations AS a,subway AS b WHERE NOT ST_Intersects(a.the_geom,ST_Buffer(b.the_geom::geography,100))",method = "GeoJSON")
Error in cartodb.collection(sql = "SELECT a.* FROM nyc_wi_fi_hotspot_locations AS a,subway AS b WHERE NOT ST_Intersects(a.the_geom,ST_Buffer(b.the_geom::geography,100))",  : 
  could not find function "cartodb.collection"
#Plot first 100 tree buffers
plot(wifi_hotspot_without_subway_routes.SP,col = "red")
plot(subway_routes.SP,add=TRUE)

Red points show some wifi hotspots don’t locate within 100m from the subway routes.

wifi_hotspot_without_bicycle_routes <- cartodb.collection(sql = "SELECT a.* FROM nyc_wi_fi_hotspot_locations AS a,bicycle_routes AS b WHERE NOT ST_Intersects(a.the_geom,ST_Buffer(b.the_geom::geography,100))",method = "GeoJSON")
wifi_hotspot_without_bicycle_routes.SP <- readOGR(wifi_hotspot_without_bicycle_routes,layer = 'OGRGeoJSON',verbose =FALSE)
plot(wifi_hotspot_without_bicycle_routes.SP,col = "red")
plot(bicycle_routes.SP,add=TRUE)

Red points show some wifi hotspots don’t locate within 100m from the bicycle routes.

wifi_hotspot_without_subway_bicycle_routes <- cartodb.collection(sql = "SELECT a.* FROM nyc_wi_fi_hotspot_locations AS a,bicycle_routes AS b,subway AS c WHERE NOT ST_Intersects(a.the_geom,ST_Buffer(b.the_geom::geography,100)) AND NOT ST_Intersects(a.the_geom,ST_Buffer(c.the_geom::geography,100))",method = "GeoJSON")

wifi_hotspot_without_subway_bicycle_routes.SP <- readOGR(wifi_hotspot_without_subway_bicycle_routes,layer = 'OGRGeoJSON',verbose =FALSE)

Only one point is neither in the buffer of the subway line nor in the buffer of the bicycle routes

wifi_hotspot_without_subway_routes_table <- cartodb.collection(sql = "SELECT a.* FROM nyc_wi_fi_hotspot_locations AS a,subway AS b WHERE NOT ST_Intersects(a.the_geom,ST_Buffer(b.the_geom::geography,100))")

4.Results and Conclusion

  1. The number of free wifi hotspots is different in different boroughs in New York City. There is the largest number of wifi hotspots in Manhattan.

  2. From the signal coverage maps above, most subway lines are covered by strong wireless network signals. On the other hand, most bicycle routes don’t covered by wifi signals. When there are some emergencies along these routes, people may not get Wi-Fi support.

c.Most Wi-Fi stations are highly utilized.They provide wifi for passengers on the subway or cyclists.

  1. Build wifi database to record the behavior data of people from wifi stations.These data can in turn help Wi-Fi station site selection. Except this, this dataset can help analyze other urban issues.

  2. It can be a good way that recruiting merchant financing by sharing wifi data to improve the construction of basic wifi hotspot.

  3. Promote healthy lifestyles to organize cycling activities to attract investment and improve infrastructure.

5. References

Author information

LS0tCnRpdGxlOiAiV0lGSSBob3RzcG90IGFuYWx5c2lzIGJhc2VkIE5ZQyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKLS0tCiMjIDEuSW50cm9kdWN0aW9uCldpLUZpIG5ldHdvcmtzIGFyZSBub3cgbW9yZSBhbmQgbW9yZSBwb3B1bGFyIGFtb25nIHVyYmFuIHJlc2lkZW50cy4gU29tZSBwdWJsaWMgcGxhY2VzIG9yIHByaXZhdGUgcGxhY2VzIGhhdmUgcHJvdmlkZWQgV2ktRmkgbmV0d29ya3MgdG8gdGhlIHB1YmxpYyBmcmVlIG9mIGNoYXJnZS4gUHVibGljIFdpLUZpIGJyaW5ncyBjb252ZW5pZW5jZSB0byBwZW9wbGUncyBsaXZlcyBhbmQgdHJhbnNwb3J0YXRpb24uIE9uIHRoZSBvdGhlciBoYW5kLCBwZW9wbGUncyBiZWhhdmlvciBkYXRhIHJlY29yZGVkIGJ5IFdpLUZpIGlzIGFuIGltcG9ydGFudCBkYXRhIHNvdXJjZS4gSXQgY2FuIHByb3ZpZGUgZGF0YSBmb3IgYmV0dGVyIHVyYmFuIHBsYW5uaW5nLiBPZiBjb3Vyc2UsIHRoZXJlIGlzIGFsc28gYSBjZXJ0YWluIGNvbW1lcmNpYWwgdmFsdWUuIFRoZSBjb25zdHJ1Y3Rpb24gb2YgcHVibGljIFdpLUZpIGluIHRoZSBjaXR5IGlzIGFuIGltcG9ydGFudCBzdGVwIGluIGJ1aWxkaW5nIGEgc21hcnQgY2l0eS4gUmVhc29uYWJsZSBzaXRlIHNlbGVjdGlvbiBjYW4gaW1wcm92ZSB0aGUgZWZmaWNpZW5jeSBvZiByZXNvdXJjZSB1dGlsaXphdGlvbi4gCgojIyAyLlRoZW1lIFJldmlldwpUaGUgc3Vid2F5IGlzIGEgZ29vZCB3YXkgdG8gdHJhdmVsIG9uIHdlZWtkYXlzLCBpdCB3b24ndCBiZSBhZmZlY3RlZCBieSB0cmFmZmljIGphbXMgY29tcGFyZWQgdG8gb3RoZXIgbW9kZXMgb2YgdHJhbnNwb3J0YXRpb24uSW4gdGhlIHNwYXJlIHRpbWUsIGN5Y2xpbmcgaXMgYSBncmVhdCB3YXkgdG8gcmVsYXggYW5kIGV4ZXJjaXNlLlRoaXMgbm90ZWJvb2sgYW5hbHl6ZXMgdGhlIGN1cnJlbnQgV2ktRmkgc3RhdGlvbiBhbmQgdHJhZmZpYyBkYXRhKFN1YndheSBhbmQgQmljeWNsZSkgaW4gTmV3IFlvcmsgQ2l0eSwgZmluZHMgcG90ZW50aWFsIGRlZmljaWVuY2llcywgYW5kIHByb3Bvc2VzIGNvcnJlc3BvbmRpbmcgc3RyYXRlZ2llcy4KCiMjIDMuRGF0YSBhbmQgTWV0aG9kcwpEYXRhOiAxKSBOWUMgRnJlZSBQdWJsaWMgV2ktRmkgMikgTllDIFN1YndheSBSb3V0ZXMgMykgTllDIFN1YndheSBTdGF0aW9ucyA0KSBOWUMgQmljeWNsZSBSb3V0ZXMgNSkgTllDIEJpY3ljbGUgUGFya2luZyBTaGVsdGVycwoKIyMjIGEuU3RhdGlzdGljcyBBbmFseXNpcyBhbmQgRGF0YSBWaXN1YWxpemF0aW9uCgpgYGB7cn0KIyBzZXQgd29ya2luZyBwYXRoCmdldHdkKCkKc2V0d2QoJy9Vc2Vycy9hZmVuL0RvY3VtZW50cy9HaXRIdWIvV0lGSV9ob3RzcG90X2FuYWx5c2lzX2Jhc2VkX05ZQycpCmBgYAoKYGBge3J9CiMgbG9hZCBkYXRhCiMgZGF0YSByZXNvdXJjZTogaHR0cHM6Ly9kYXRhLmNpdHlvZm5ld3lvcmsudXMvU29jaWFsLVNlcnZpY2VzL05ZQy1XaS1GaS1Ib3RzcG90LUxvY2F0aW9ucy8Kd2lmaV9kYXRhIDwtIHJlYWQuY3N2KCcuL2RhdGEvTllDX0ZyZWVfUHVibGljX1dpRmlfMDMyOTIwMTcuY3N2JykKaGVhZCh3aWZpX2RhdGEpCm5hbWVzKHdpZmlfZGF0YSkKYGBgCgpgYGB7cn0KIyBzdWJzZXQgdGhlIGRhdGEgc2VsZWN0IGludGVyZXN0aW5nIGNvbHVtbnMKd2lmaV9kYXRhIDwtIHN1YnNldCh3aWZpX2RhdGEsc2VsZWN0ID0gYygidGhlX2dlb20iLCJUWVBFIiwiUFJPVklERVIiLCJMQVQiLCJMT0NBVElPTiIsIkxPTiIsIlgiLCJZIiwiQk9ST05BTUUiKSkKIyBzdW1tYXJ5IGRhdGEKaGVhZCh3aWZpX2RhdGEpCnN1bW1hcnkod2lmaV9kYXRhKQpgYGAKCmBgYHtyfQojIERhdGEgdmlzdWFsaXphdGlvbgpsaWJyYXJ5KGdncGxvdDIpCmBgYAoKYGBge3J9CmxpYnJhcnkoc2NhbGVzKQojIHBsb3QgYmFyIGdyYXBoIHRvIHNob3cgZGF0YSBkaXN0cmlidXRpb24Kd2lmaV9wcm8gPC0gZ2dwbG90KHdpZmlfZGF0YSxhZXMoUFJPVklERVIpKQp3aWZpX3BybyArIGdlb21fYmFyKGFlcyhmaWxsPVRZUEUpKSArIHNjYWxlX2ZpbGxfYnJld2VyKGRpcmVjdGlvbiA9IC0xLHBhbGV0dGUgPSAiR3JlZW4iKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91cj0iZ3JleTIwIixzaXplID0gNSxhbmdsZT00NSxoanVzdD0uNSx2anVzdD0uNSxmYWNlPSJwbGFpbiIpKQpgYGAKCmBgYHtyfQp3aWZpX2Jvcm8gPC0gZ2dwbG90KHdpZmlfZGF0YSxhZXMoQk9ST05BTUUpKQp3aWZpX2Jvcm8gKyBnZW9tX2JhcihhZXMoZmlsbD1UWVBFKSkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIkdyZWVuIixkaXJlY3Rpb24gPSAtMSkKYGBgCkNob3JvcGxldGggYW5kIEhlYXQgbWFwIHBvd2VyZWQgYnkgY2FydG9baHR0cHM6Ly9jYXJ0by5jb20vXQohW0Nob3JvcGxldGggYW5kIEhlYXQgbWFwXSguL2ltYWdlL0Nob3JvcGxldGggYW5kIEhlYXQgbWFwLnBuZykKCiMjIyBiLlNwYXRpYWwgUXVlcmllcyBhbmQgU3BhdGlhbCBBbmFseXNpcwpgYGB7cn0KIyB1c2UgY2FydG9kYiB0byBkbyBhbmFseXNpcyBmcm9tIHNwYXRpYWwgZGF0YWJhc2UKbGlicmFyeShSQ3VybCkKbGlicmFyeShiaXRvcHMpCmxpYnJhcnkoUkpTT05JTykKbGlicmFyeShkZXZ0b29scykKbGlicmFyeShDYXJ0b0RCKQpgYGAKCmBgYHtyfQojIGNvbm5lY3QgdG8gb3VyIGFjY291bnQKY2FydG9kYigiemhvdW1hbmVvIikKY2FydG9kYi50ZXN0KCkKYGBgCgpgYGB7cn0KY2FydG9kYigiemhvdW1hbmVvIiwgYXBpLmtleT0iZmIwNzA3OTlhY2FkMjFkNjI2YjVhZGU5NGNhYTM1NDJiN2RlY2Q4OCIpCmBgYAoKIyMjIyAxKSBEbyBzb21lIHNwYXRpYWwgcXVlcmllcyBhbmQgcGxvdCB0aGUgcmVzdWx0cwoKYGBge3J9CmxpYnJhcnkocmdkYWwpCiMgU3BhdGlsYSBRdWVyaWVzIGJhc2VkIG9uIHJlcXVpcm1lbnRzCmJpY3ljbGVfcm91dGVzIDwtIGNhcnRvZGIuY29sbGVjdGlvbihzcWw9IlNFTEVDVCAqIEZST00gYmljeWNsZV9yb3V0ZXMiLG1ldGhvZD0iR2VvSlNPTiIpCmJpY3ljbGVfcm91dGVzLlNQIDwtIHJlYWRPR1IoYmljeWNsZV9yb3V0ZXMsbGF5ZXIgPSAnT0dSR2VvSlNPTicsdmVyYm9zZSA9RkFMU0UpCkZyZWVfd2lmaV9ob3RzcG90IDwtIGNhcnRvZGIuY29sbGVjdGlvbihzcWwgPSAiU0VMRUNUICogRlJPTSBueWNfd2lfZmlfaG90c3BvdF9sb2NhdGlvbnMgV0hFUkUgdHlwZSA9ICdGcmVlJyIsbWV0aG9kID0gIkdlb0pTT04iKQpGcmVlX3dpZmlfaG90c3BvdC5TUCA8LSByZWFkT0dSKEZyZWVfd2lmaV9ob3RzcG90LGxheWVyID0gJ09HUkdlb0pTT04nLHZlcmJvc2UgPSBGQUxTRSkKYmljeWNsZV9wYXJraW5nX3NoZWx0ZXJzIDwtIGNhcnRvZGIuY29sbGVjdGlvbihzcWw9IlNFTEVDVCAqIEZST00gYmljeWNsZV9wYXJraW5nX3NoZWx0ZXJzIixtZXRob2QgPSAiR2VvSlNPTiIpCmJpY3ljbGVfcGFya2luZ19zaGVsdGVycy5TUCA8LSByZWFkT0dSKGJpY3ljbGVfcGFya2luZ19zaGVsdGVycyxsYXllciA9ICdPR1JHZW9KU09OJyx2ZXJib3NlID0gRkFMU0UpCmBgYAoKVGhpcyBwbG90IGlzIHRvIHNob3cgdGhlIGxvY2F0aW9uIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGZyZWUgd2lmaSBob3RzcG90IGFuZCBiaWN5Y2xlIHJvdXRlcwoKYGBge3J9CiMgcGxvdCB0aGUgcmVzdWx0cyBvZiBxdWVyaWVzCnBsb3QoYmljeWNsZV9yb3V0ZXMuU1ApCnBsb3QoRnJlZV93aWZpX2hvdHNwb3QuU1AsY29sID0gInJlZCIsYWRkID0gVFJVRSkKcGxvdChiaWN5Y2xlX3Bhcmtpbmdfc2hlbHRlcnMuU1AsY29sID0gImdyZWVuIixhZGQgPSBUUlVFLCBwY2ggPSAyMCkKYGBgCgpgYGB7cn0KTGltaXRlZF9mcmVlX3dpZmlfaG90c3BvdCA8LSBjYXJ0b2RiLmNvbGxlY3Rpb24oc3FsID0gIlNFTEVDVCAqIEZST00gbnljX3dpX2ZpX2hvdHNwb3RfbG9jYXRpb25zIFdIRVJFIHR5cGUgPSAnTGltaXRlZCBGcmVlJyIsbWV0aG9kID0gIkdlb0pTT04iKQpMaW1pdGVkX2ZyZWVfd2lmaV9ob3RzcG90LlNQIDwtIHJlYWRPR1IoTGltaXRlZF9mcmVlX3dpZmlfaG90c3BvdCxsYXllciA9ICdPR1JHZW9KU09OJyx2ZXJib3NlID0gRkFMU0UpCmBgYAoKVGhpcyBwbG90IGlzIHRvIHNob3cgdGhlIGxvY2F0aW9uIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGxpbWl0ZWQgZnJlZSB3aWZpIGhvdHNwb3QgYW5kIGJpY3ljbGUgcm91dGVzCgpgYGB7cn0KcGxvdChiaWN5Y2xlX3JvdXRlcy5TUCkKcGxvdChMaW1pdGVkX2ZyZWVfd2lmaV9ob3RzcG90LlNQLGNvbCA9ICJyZWQiLGFkZCA9IFRSVUUpCnBsb3QoYmljeWNsZV9wYXJraW5nX3NoZWx0ZXJzLlNQLCBjb2wgPSAiZ3JlZW4iLGFkZCA9IFRSVUUsIHBjaCA9IDIwKQpgYGAKCmBgYHtyfQpzdWJ3YXlfcm91dGVzIDwtIGNhcnRvZGIuY29sbGVjdGlvbihzcWwgPSAiU0VMRUNUICogRlJPTSBzdWJ3YXkiLG1ldGhvZCA9ICJHZW9KU09OIikKc3Vid2F5X3JvdXRlcy5TUCA8LSByZWFkT0dSKHN1YndheV9yb3V0ZXMsbGF5ZXIgPSAnT0dSR2VvSlNPTicsdmVyYm9zZSA9IEZBTFNFKQpzdWJ3YXlfc3RhdGlvbnMgPC0gY2FydG9kYi5jb2xsZWN0aW9uKHNxbCA9ICJTRUxFQ1QgKiBGUk9NIHN1YndheV9zdGF0aW9ucyIsbWV0aG9kID0gIkdlb0pTT04iKQpzdWJ3YXlfc3RhdGlvbnMuU1AgPC0gcmVhZE9HUihzdWJ3YXlfc3RhdGlvbnMsbGF5ZXIgPSAnT0dSR2VvSlNPTicsdmVyYm9zZSA9IEZBTFNFKQpgYGAKClRoaXMgcGxvdCBpcyB0byBzaG93IHRoZSBsb2NhdGlvbiByZWxhdGlvbnNoaXAgYmV0d2VlbiB3aWZpIGhvdHNwb3QgYW5kIHN1YndheSByb3V0ZXMKCmBgYHtyfQojIHRvIHNob3cgc3BhdGlhbCByZWxhdGlvbnNoaXAgYWJvdXQgc3Vid2F5IHJvdXRlcyBhbmQgd2lmaSBob3RzcG90cwpwbG90KHN1YndheV9yb3V0ZXMuU1ApCnBsb3Qoc3Vid2F5X3N0YXRpb25zLlNQLGFkZCA9IFRSVUUpCnBsb3QoRnJlZV93aWZpX2hvdHNwb3QuU1AsY29sID0gImdyZWVuIixhZGQgPSBUUlVFKQpwbG90KExpbWl0ZWRfZnJlZV93aWZpX2hvdHNwb3QuU1AsY29sID0gImRhcmsgZ3JlZW4iLGFkZCA9IFRSVUUpCmBgYAojIyMjIDIpIFNwYXRpYWwgYW5hbHlzaXMKVGhlIHdpZmkgc2lnbmFsIGlzIHNwcmVhZCBvdXQgYnkgdGhlIHdpZmkgc3RhdGlvbi4gVGhlIHNpZ25hbCBzdHJlbmd0aCBkZWNyZWFzZXMgd2l0aCBkaXN0YW5jZS4gR2VuZXJhbGx5LCB0aGUgV2ktRmkgc2lnbmFsIGhhcyBhIHJhZGlhdGlvbiBkaXN0YW5jZSBvZiBsZXNzIHRoYW4gMTAwbS4gClRoaXMgbm90ZWJvb2sgdXNlcyAxMDBtIGFzIHJhbmdlIHRvIGRvIGJ1ZmZlciBhcyB0aGUgem9uZXMgb2Ygc2lnbmFsIGNvdmVyZWQuIEFuZCB0aGVuIGRvIHNvbWUgc3BhdGlhbCBpbnRlcnNlY3QgYW5hbHlzaXMgdG8gc2VlIHRoZSBzaWduYWwgY292ZXJhZ2Ugb2YgdmFyaW91cyBzdWJ3YXkgbGluZXMgYW5kIGJpY3ljbGUgcm91dGVzLiBGaW5hbGx5LCBJIGFsc28gdXNlIGJ1ZmZlciBhbmQgaW50ZXJzZWN0aW9uIHRvIHNlZSB0aGUgdXRpbGl6YXRpb25zIG9mIHdpZmkgaG90c3BvdC4KYGBge3J9CiMgQnVmZmVyIGFuYWx5c2lzCiMgQnVmZmVyIHdpZmkgaG90c3BvdCBkYXRhIHRvIDEwMG0gcmFuZ2UKd2lmaV9idWZmZXJzIDwtIGNhcnRvZGIuY29sbGVjdGlvbihzcWw9IlNFTEVDVCBjYXJ0b2RiX2lkLCAgU1RfQnVmZmVyKHRoZV9nZW9tOjpnZW9ncmFwaHksMTAwKSBhcyB0aGVfZ2VvbSBGUk9NIG55Y193aV9maV9ob3RzcG90X2xvY2F0aW9ucyIsbWV0aG9kPSJHZW9KU09OIikKCndpZmlfYnVmZmVycy5TUCA8LSByZWFkT0dSKHdpZmlfYnVmZmVycyxsYXllciA9ICdPR1JHZW9KU09OJyx2ZXJib3NlID1GQUxTRSkKCnBsb3Qod2lmaV9idWZmZXJzLlNQWzE6MTAwLF0pCmBgYAoKKiBXaWZpIGhvdHNwb3QgbG9jYXRpb25zIGJ1ZmZlciBieSBjYXJ0bwohW3dpZmkgYnVmZmVyXSguL2ltYWdlL3dpZmkgYnVmZmVyLnBuZykKCiogVGhlIHNpZ25hbCBjb3ZlcmFnZSBvZiB2YXJpb3VzIHN1YndheSBsaW5lcy4KIVtzdWJ3YXlfcm91dGVzXSguL2ltYWdlL3N1YndheV9yb3V0ZXMucG5nKQoKKiBUaGUgc2lnbmFsIGNvdmVyYWdlIG9mIHZhcmlvdXMgYmljeWNsZSByb3V0ZXMuCiFbYmljeWNsZSByb3V0ZXNdKC4vaW1hZ2UvYmljeWNsZSByb3V0ZXMucG5nKQoKIyMjIyAzKSBVdGlsaXphdGlvbiBvZiB3aWZpIGhvdHNwb3QKCmBgYHtyfQojIGJ1ZmZlciB0aGUgc3Vid2F5IHJvdXRlcwpzdWJ3YXlfcm91dGVzX2J1ZmZlcnMgPC0gY2FydG9kYi5jb2xsZWN0aW9uKHNxbD0iU0VMRUNUIGNhcnRvZGJfaWQsICBTVF9CdWZmZXIodGhlX2dlb206Omdlb2dyYXBoeSwxMDApIGFzIHRoZV9nZW9tIEZST00gc3Vid2F5IixtZXRob2Q9Ikdlb0pTT04iKQoKc3Vid2F5X3JvdXRlc19idWZmZXJzLlNQIDwtIHJlYWRPR1Ioc3Vid2F5X3JvdXRlc19idWZmZXJzLGxheWVyID0gJ09HUkdlb0pTT04nLHZlcmJvc2UgPUZBTFNFKQoKcGxvdChzdWJ3YXlfcm91dGVzX2J1ZmZlcnMuU1ApCmBgYApGaW5kIHRoZSB3aWZpIGhvdHNwb3RzIHRoYXQgZG8gbm90IGludGVyc2VjdCB3aXRoIHRoZSBidWZmZXIgb2Ygc3Vid2F5IHJvdXRlcwpgYGB7cn0KIyBpbnRlcnNlY3Rpb24gCndpZmlfaG90c3BvdF93aXRob3V0X3N1YndheV9yb3V0ZXMgPC0gY2FydG9kYi5jb2xsZWN0aW9uKHNxbCA9ICJTRUxFQ1QgYS4qIEZST00gbnljX3dpX2ZpX2hvdHNwb3RfbG9jYXRpb25zIEFTIGEsc3Vid2F5IEFTIGIgV0hFUkUgTk9UIFNUX0ludGVyc2VjdHMoYS50aGVfZ2VvbSxTVF9CdWZmZXIoYi50aGVfZ2VvbTo6Z2VvZ3JhcGh5LDEwMCkpIixtZXRob2QgPSAiR2VvSlNPTiIpCiMgUGxvdCB0aGUgcmVzdWx0cwp3aWZpX2hvdHNwb3Rfd2l0aG91dF9zdWJ3YXlfcm91dGVzLlNQIDwtIHJlYWRPR1Iod2lmaV9ob3RzcG90X3dpdGhvdXRfc3Vid2F5X3JvdXRlcyxsYXllciA9ICdPR1JHZW9KU09OJyx2ZXJib3NlID1GQUxTRSkKYGBgCgoKYGBge3J9CnBsb3Qod2lmaV9ob3RzcG90X3dpdGhvdXRfc3Vid2F5X3JvdXRlcy5TUCxjb2wgPSAicmVkIikKcGxvdChzdWJ3YXlfcm91dGVzLlNQLGFkZD1UUlVFKQpgYGAKUmVkIHBvaW50cyBzaG93IHNvbWUgd2lmaSBob3RzcG90cyBkb24ndCBsb2NhdGUgd2l0aGluIDEwMG0gZnJvbSB0aGUgc3Vid2F5IHJvdXRlcy4KCmBgYHtyfQp3aWZpX2hvdHNwb3Rfd2l0aG91dF9iaWN5Y2xlX3JvdXRlcyA8LSBjYXJ0b2RiLmNvbGxlY3Rpb24oc3FsID0gIlNFTEVDVCBhLiogRlJPTSBueWNfd2lfZmlfaG90c3BvdF9sb2NhdGlvbnMgQVMgYSxiaWN5Y2xlX3JvdXRlcyBBUyBiIFdIRVJFIE5PVCBTVF9JbnRlcnNlY3RzKGEudGhlX2dlb20sU1RfQnVmZmVyKGIudGhlX2dlb206Omdlb2dyYXBoeSwxMDApKSIsbWV0aG9kID0gIkdlb0pTT04iKQoKd2lmaV9ob3RzcG90X3dpdGhvdXRfYmljeWNsZV9yb3V0ZXMuU1AgPC0gcmVhZE9HUih3aWZpX2hvdHNwb3Rfd2l0aG91dF9iaWN5Y2xlX3JvdXRlcyxsYXllciA9ICdPR1JHZW9KU09OJyx2ZXJib3NlID1GQUxTRSkKYGBgCgpgYGB7cn0KcGxvdCh3aWZpX2hvdHNwb3Rfd2l0aG91dF9iaWN5Y2xlX3JvdXRlcy5TUCxjb2wgPSAicmVkIikKcGxvdChiaWN5Y2xlX3JvdXRlcy5TUCxhZGQ9VFJVRSkKYGBgClJlZCBwb2ludHMgc2hvdyBzb21lIHdpZmkgaG90c3BvdHMgZG9uJ3QgbG9jYXRlIHdpdGhpbiAxMDBtIGZyb20gdGhlIGJpY3ljbGUgcm91dGVzLgoKYGBge3J9CndpZmlfaG90c3BvdF93aXRob3V0X3N1YndheV9iaWN5Y2xlX3JvdXRlcyA8LSBjYXJ0b2RiLmNvbGxlY3Rpb24oc3FsID0gIlNFTEVDVCBhLiogRlJPTSBueWNfd2lfZmlfaG90c3BvdF9sb2NhdGlvbnMgQVMgYSxiaWN5Y2xlX3JvdXRlcyBBUyBiLHN1YndheSBBUyBjIFdIRVJFIE5PVCBTVF9JbnRlcnNlY3RzKGEudGhlX2dlb20sU1RfQnVmZmVyKGIudGhlX2dlb206Omdlb2dyYXBoeSwxMDApKSBBTkQgTk9UIFNUX0ludGVyc2VjdHMoYS50aGVfZ2VvbSxTVF9CdWZmZXIoYy50aGVfZ2VvbTo6Z2VvZ3JhcGh5LDEwMCkpIixtZXRob2QgPSAiR2VvSlNPTiIpCgp3aWZpX2hvdHNwb3Rfd2l0aG91dF9zdWJ3YXlfYmljeWNsZV9yb3V0ZXMuU1AgPC0gcmVhZE9HUih3aWZpX2hvdHNwb3Rfd2l0aG91dF9zdWJ3YXlfYmljeWNsZV9yb3V0ZXMsbGF5ZXIgPSAnT0dSR2VvSlNPTicsdmVyYm9zZSA9RkFMU0UpCmBgYAoKYGBge3J9CnBsb3Qod2lmaV9ob3RzcG90X3dpdGhvdXRfc3Vid2F5X2JpY3ljbGVfcm91dGVzLlNQLGNvbCA9ICJyZWQiKQpgYGAKT25seSBvbmUgcG9pbnQgaXMgbmVpdGhlciBpbiB0aGUgYnVmZmVyIG9mIHRoZSBzdWJ3YXkgbGluZSBub3IgaW4gdGhlIGJ1ZmZlciBvZiB0aGUgYmljeWNsZSByb3V0ZXMKCmBgYHtyfQp3aWZpX2hvdHNwb3Rfd2l0aG91dF9zdWJ3YXlfcm91dGVzX3RhYmxlIDwtIGNhcnRvZGIuY29sbGVjdGlvbihzcWwgPSAiU0VMRUNUIGEuKiBGUk9NIG55Y193aV9maV9ob3RzcG90X2xvY2F0aW9ucyBBUyBhLHN1YndheSBBUyBiIFdIRVJFIE5PVCBTVF9JbnRlcnNlY3RzKGEudGhlX2dlb20sU1RfQnVmZmVyKGIudGhlX2dlb206Omdlb2dyYXBoeSwxMDApKSIpCmBgYAoKIyMgNC5SZXN1bHRzIGFuZCBDb25jbHVzaW9uCgoqIFJlc3VsdHMKCiBhLiBUaGUgbnVtYmVyIG9mIGZyZWUgd2lmaSBob3RzcG90cyBpcyBkaWZmZXJlbnQgaW4gZGlmZmVyZW50IGJvcm91Z2hzIGluIE5ldyBZb3JrIENpdHkuIFRoZXJlIGlzIHRoZSBsYXJnZXN0IG51bWJlciBvZiB3aWZpIGhvdHNwb3RzIGluIE1hbmhhdHRhbi4KIAogYi4gRnJvbSB0aGUgc2lnbmFsIGNvdmVyYWdlIG1hcHMgYWJvdmUsIG1vc3Qgc3Vid2F5IGxpbmVzIGFyZSBjb3ZlcmVkIGJ5IHN0cm9uZyB3aXJlbGVzcyBuZXR3b3JrIHNpZ25hbHMuIE9uIHRoZSBvdGhlciBoYW5kLCBtb3N0IGJpY3ljbGUgcm91dGVzIGRvbid0IGNvdmVyZWQgYnkgd2lmaSBzaWduYWxzLiBXaGVuIHRoZXJlIGFyZSBzb21lIGVtZXJnZW5jaWVzIGFsb25nIHRoZXNlIHJvdXRlcywgcGVvcGxlIG1heSBub3QgZ2V0IFdpLUZpIHN1cHBvcnQuCiAKIGMuTW9zdCBXaS1GaSBzdGF0aW9ucyBhcmUgaGlnaGx5IHV0aWxpemVkLlRoZXkgcHJvdmlkZSB3aWZpIGZvciBwYXNzZW5nZXJzIG9uIHRoZSBzdWJ3YXkgb3IgY3ljbGlzdHMuCiAKKiBTdHJhdGVnaWVzCgogYS4gQnVpbGQgd2lmaSBkYXRhYmFzZSB0byByZWNvcmQgdGhlIGJlaGF2aW9yIGRhdGEgb2YgcGVvcGxlIGZyb20gd2lmaSBzdGF0aW9ucy5UaGVzZSBkYXRhIGNhbiBpbiB0dXJuIGhlbHAgV2ktRmkgc3RhdGlvbiBzaXRlIHNlbGVjdGlvbi4gRXhjZXB0IHRoaXMsIHRoaXMgZGF0YXNldCBjYW4gaGVscCBhbmFseXplIG90aGVyIHVyYmFuIGlzc3Vlcy4KIAogYi4gSXQgY2FuIGJlIGEgZ29vZCB3YXkgdGhhdCByZWNydWl0aW5nIG1lcmNoYW50IGZpbmFuY2luZyBieSBzaGFyaW5nIHdpZmkgZGF0YSB0byBpbXByb3ZlIHRoZSBjb25zdHJ1Y3Rpb24gb2YgYmFzaWMgd2lmaSBob3RzcG90LgogCiBjLiBQcm9tb3RlIGhlYWx0aHkgbGlmZXN0eWxlcyB0byBvcmdhbml6ZSBjeWNsaW5nIGFjdGl2aXRpZXMgdG8gYXR0cmFjdCBpbnZlc3RtZW50IGFuZCBpbXByb3ZlIGluZnJhc3RydWN0dXJlLgoKIyMgNS4JUmVmZXJlbmNlcwoKICogU2V1ZmVydCwgR3JpZXBlbnRyb2csIEJ1cmdlciwgJiBIb2JmZWxkLiAoMjAxNikuIEEgU2ltcGxlIFdpRmkgSG90c3BvdCBNb2RlbCBmb3IgQ2l0aWVzLiBDb21tdW5pY2F0aW9ucyBMZXR0ZXJzLCBJRUVFLCAyMCgyKSwgMzg0LTM4Ny4KIAogKiBHb3dleC4gKDIwMTMpLiBHb3dleCB0byBtZXJnZSBwdWJsaWMsIHByaXZhdGUgV2lGaSB0byBjcmVhdGUgc21hcnQgY2l0eSBob3RzcG90IG5ldHdvcmtzLiBUb3RhbCBUZWxlY29tIE1hZ2F6aW5lLCBUb3RhbCBUZWxlY29tIE1hZ2F6aW5lLCBOb3YgNSwgMjAxMy4KIAogKiBEYXRhIFZpc3VhbGl6YXRpb24gd2l0aCBnZ3Bsb3QyIENoZWF0IFNoZWV0IFtodHRwczovL3d3dy5yc3R1ZGlvLmNvbS93cC1jb250ZW50L3VwbG9hZHMvMjAxNS8wMy9nZ3Bsb3QyLWNoZWF0c2hlZXQucGRmXQogCiAqIENhcnRvREJbaHR0cHM6Ly9naXRodWIuY29tL0NhcnRvREIvY2FydG9kYl0KIAogCiMjIyBBdXRob3IgaW5mb3JtYXRpb24KICogTmFtZTogWkhPVSBZaW1pbiAKICogU3R1ZGVudCBJRDogMTgwODczMjVnCiAqIFJlc291cmNlOiBbaHR0cHM6Ly9naXRodWIuY29tL3pob3VtYW5lby9XSUZJX2hvdHNwb3RfYW5hbHlzaXNfYmFzZWRfTllDXQogCg==